package processes

import (
	"encoding/json"
	"fmt"
	message "learningProject/shangguigu/common"
	"learningProject/shangguigu/server/model"
	"learningProject/shangguigu/server/utils"
	"net"
)

type UserProcess struct {
	Conn net.Conn
	// 增加一个字段，表示该conn是哪个用户的
	UserId int
}

// 通知所有在线用户
// userId要通知其他的在线用户 我上线了
func (this *UserProcess) NotifyOthersOnlineUser(userId int) {
	// 遍历onlineUsers 然后一个个发送 NotifyUserStatusMes
	for id, up := range userMgr.onlineUsers {
		// 过滤掉自己
		if id == userId {
			continue
		}
		// 剩下的一个个通知
		up.NotifyMeOnline(userId)
	}

}

func (this *UserProcess) NotifyMeOnline(userId int) {
	var mes message.Message
	mes.Type = message.NotifyUserStatusMesType

	var notifyUserStatusMes message.NotifyUserStatusMes
	notifyUserStatusMes.UserId = userId
	notifyUserStatusMes.Status = message.UserOnline

	// 序列化
	data, err := json.Marshal(notifyUserStatusMes)
	if err != nil {
		fmt.Println("json.Marshal err = ", err)
		return
	}

	mes.Data = string(data)
	data, err = json.Marshal(mes)
	if err != nil {
		fmt.Println("json.Marshal err = ", err)
		return
	}

	tf := &utils.Transfer{
		Conn: this.Conn, // 将UserProcess结构体的Conn赋给utils包下的Transfer结构体
	}
	err = tf.WritePkg(data)
	if err != nil {
		fmt.Println("NotifyMeOnline err")
		return
	}
}

// 处理注册请求
func (this *UserProcess) ServerProcessRegister(mes *message.Message) (err error) {
	var registerMeg message.RegisterMeg
	err = json.Unmarshal([]byte(mes.Data), &registerMeg) //mes.Data是string类型，要强转
	if err != nil {
		fmt.Println("json.Unmarshal mes.Data err")
		return
	}

	// 声明服务器要返回的消息
	var resMes message.Message
	resMes.Type = message.RegisterResMegTYpe
	var registerResMes message.RegisterResMeg
	// 完成注册
	err = model.MyUserDao.Register(&registerMeg.User)
	if err != nil {
		if err == model.ERROR_USER_EXISTS {
			registerResMes.Code = 404
			registerResMes.Error = model.ERROR_USER_EXISTS.Error()
		} else {
			registerResMes.Code = 506
			registerResMes.Error = "注册发生未知错误"
		}
	} else {
		registerResMes.Code = 200
	}

	data, err := json.Marshal(registerResMes)
	if err != nil {
		fmt.Println("json.Marshal registerResMes err = ", err)
		return
	}

	resMes.Data = string(data) // data是byte切片,要转成string

	// 将resMes序列化
	data, err = json.Marshal(resMes) // 这里的data就是要发送的数据
	if err != nil {
		fmt.Println("json.Marshal resMes err = ", err)
		return
	}

	tf := &utils.Transfer{
		Conn: this.Conn, // 将UserProcess结构体的Conn赋给utils包下的Transfer结构体
	}
	err = tf.WritePkg(data)
	return
}

// 处理登录请求
func (this *UserProcess) ServerProcessLogin(mes *message.Message) (err error) {
	// 先从mes中取出 mes.Data 并反序列化成LoginMes
	var loginMes message.LoginMes
	err = json.Unmarshal([]byte(mes.Data), &loginMes) //mes.Data是string类型，要强转
	if err != nil {
		fmt.Println("json.Unmarshal mes.Data err")
		return
	}

	// 声明服务器要返回的消息
	var resMes message.Message
	resMes.Type = message.LoginResMegType
	// 创建一个ResMeg结构体
	var loginResMes message.LoginResMeg

	// 去redis数据库验证数据
	// model.UserDao
	user, err := model.MyUserDao.Login(loginMes.UserId, loginMes.UserPwd)
	fmt.Println(user)
	if err != nil {
		if err == model.ERROR_USER_NOTEXISTS {
			loginResMes.Code = 500
			loginResMes.Error = err.Error()
		} else if err == model.ERROR_USER_PWD {
			loginResMes.Code = 403
			loginResMes.Error = err.Error()
		} else {
			loginResMes.Code = 505
			fmt.Println("服务器内部错误")
		}

	} else {
		loginResMes.Code = 200
		// 这里用户登录成功，将该用户放入userMgr字段中
		// 将登录成功的Userid赋给this
		this.UserId = loginMes.UserId
		userMgr.AddonlineUsers(this)
		// 通知其他在线用户我上线了
		this.NotifyOthersOnlineUser(loginMes.UserId)
		// 将当前在线用户的id放入loginResMes.UserIds
		// 遍历userMgr.onlineUsers
		for id, _ := range userMgr.onlineUsers {
			loginResMes.UserIds = append(loginResMes.UserIds, id)
		}
		fmt.Println("登录成功")
	}

	// 将loginResMes序列化，然后放入mes的Data
	data, err := json.Marshal(loginResMes)
	if err != nil {
		fmt.Println("json.Marshal loginResMes err = ", err)
		return
	}

	resMes.Data = string(data) // data是byte切片,要转成string

	// 将resMes序列化
	data, err = json.Marshal(resMes) // 这里的data就是要发送的数据
	if err != nil {
		fmt.Println("json.Marshal resMes err = ", err)
		return
	}

	// 发送数据
	// 注意这里赋值的格式！！！！！
	// 创建Transfer实例
	tf := &utils.Transfer{
		Conn: this.Conn, // 将UserProcess结构体的Conn赋给utils包下的Transfer结构体
	}
	err = tf.WritePkg(data)
	return

}
